#include "LecteurPhraseSimple.h"

#include <stdlib.h>
#include <iostream>
using namespace std;

////////////////////////////////////////////////////////////////////////////////
LecteurPhraseSimple::LecteurPhraseSimple(string nomFich) :
	ls(nomFich) {
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::analyse() {
	programme();
	cout << "Syntaxe correcte." << endl;
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::programme() {
// <programme> ::= debut <seqInst> fin FIN_FICHIER

	sauterSymCour("debut");
	seqInst();
	sauterSymCour("fin");
	testerSymCour("<FINDEFICHIER>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::seqInst() {
// <seqInst> ::= <inst> ; { <inst> ; }

	do {
		inst();
	} while (ls.getSymCour()=="<VARIABLE>" || ls.getSymCour()=="si" || ls.getSymCour()=="tantque" || ls.getSymCour()=="repeter" || ls.getSymCour()=="pour");
	// tant que le symbole courant est un debut possible d'instruction...
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::inst()
{
// <inst> ::= <affectation> | <instSi> | <instTq> | <instRepeter> | <pour>

	if(ls.getSymCour() == "si")
	{
		sauterSymCour("si");
		instSi();
	}
	else if(ls.getSymCour() == "tantque")
	{
		sauterSymCour("tantque");
		instTq();
	}
	else if(ls.getSymCour() == "repeter")
	{
		sauterSymCour("repeter");
		instRepeter();
	}
	else if(ls.getSymCour() == "lire")
	{
		sauterSymCour("lire");
		instLire();
	}
	else if(ls.getSymCour() == "ecrire")
	{
		sauterSymCour("ecrire");
		instEcrire();
	}
	else if(ls.getSymCour() == "pour")
	{
		sauterSymCour("pour");
		instPour();
	}
	else
	{
		affectation();
		sauterSymCour(";");
	}
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::instPour()
{
	if(ls.getSymCour()=="(")
	{
		sauterSymCour("(");
		affectation();
		if(ls.getSymCour()==";")
		{
			sauterSymCour(";");
			expBool();
			if(ls.getSymCour()==";")
			{
				sauterSymCour(";");
				affectation();
				if(ls.getSymCour()==")")
				{
					sauterSymCour(")");
					if(ls.getSymCour()=="{")
					{
						sauterSymCour("{");
						seqInst();
						if(ls.getSymCour()=="}")
							sauterSymCour("}");
						else
							erreur("<instPour6>");
					}
					else
						erreur("<instPour5>");
				}
				else
					erreur("<instPour4>");
			}
			else
				erreur("<instPour3>");
		}
		else
			erreur("<instPour2>");
	}
	else
		erreur("<instPour1>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::instRepeter()
{
	seqInst();
	sauterSymCour("jusqua");
	if (ls.getSymCour()=="(")
	{
		sauterSymCour("(");
		expBool();
		sauterSymCour(")");
	}
	else
		erreur("<instRepeter>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::instTq()
{
	if (ls.getSymCour()=="(")
	{
		sauterSymCour("(");
		expBool();
		sauterSymCour(")");
		seqInst();
		sauterSymCour("fintantque");
	}
	else
		erreur("<instTq>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::instSi()
{
	if (ls.getSymCour()=="(")
	{
		sauterSymCour("(");
		expBool();
		sauterSymCour(")");
		seqInst();
		while(ls.getSymCour()=="sinonsi")
		{
			if (ls.getSymCour()=="(")
			{
				expBool();
				sauterSymCour(")");
				seqInst();
			}
			else
				erreur("<instSi_2>");
		}
		if(ls.getSymCour()=="sinon")
			seqInst();
		sauterSymCour("finsi");
	}
	else
		erreur("<instSi_1>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::instLire()
{
	if (ls.getSymCour()=="(")
	{
		sauterSymCour("(");
		sauterSymCour("<VARIABLE>");
		sauterSymCour(")");
	}
	else
		erreur("<instLire>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::instEcrire()
{
	if (ls.getSymCour()=="(")
	{
		sauterSymCour("(");
		if(ls.getSymCour()=="<EXPRESSION>")
			sauterSymCour("<EXPRESSION>");
		else if(ls.getSymCour()=="<CHAINE>")
			sauterSymCour("<CHAINE>");
		else
			erreur("<instEcrire>");
		sauterSymCour(")");
	}
	else
		erreur("<instLire>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::affectation() {
// <affectation> ::= <variable> = <expression>

	sauterSymCour("<VARIABLE>");
	sauterSymCour("=");
	expression();
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::expression() {
// <expression> ::= <terme> { <opAdd> <terme> }

	terme();
	while (ls.getSymCour()=="+" || ls.getSymCour()=="-")
	{
		opAdd();
		terme();
	}
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::terme() {
// <terme> ::= <facteur> { <opMult> <facteur> }

	facteur();
	while (ls.getSymCour()=="*" || ls.getSymCour()=="/")
	{
		opMult();
		facteur();
	}
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::expBool() {
// <expBool> ::= <expEt> { <opOu> <expEt> }

	expEt();
	while (ls.getSymCour()=="ou")
	{
		opOu();
		expEt();
	}
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::expEt() {
// <expEt> ::= <relation> { <opEt> <relation> }

	relation();
	while (ls.getSymCour()=="et")
	{
		opEt();
		relation();
	}
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::opEt() {
// <opEt> ::= et

	if (ls.getSymCour()=="et")
		ls.suivant();
	else
		erreur("<opEt>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::opOu() {
// <opBool> ::= et | ou

	if (ls.getSymCour()=="ou")
		ls.suivant();
	else
		erreur("<opOu>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::relation() {
// <relation> ::= <expression> { <opRel> <expression> }

	expression();
	while (ls.getSymCour()=="==" || ls.getSymCour()=="!=" ||
			ls.getSymCour()=="<" || ls.getSymCour()=="<=" ||
			ls.getSymCour()==">" || ls.getSymCour()==">=")
	{
		opRel();
		expression();
	}
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::opUnaire() {
// <opUnaire> ::= - | non

	if (ls.getSymCour()=="-" || ls.getSymCour()=="non")
		ls.suivant();
	else
		erreur("<opUnaire>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::opRel() {
// <opRel> ::= == | != | < | <= | > | >=

	if (ls.getSymCour()=="==" || ls.getSymCour()=="!=" ||
			ls.getSymCour()=="<" || ls.getSymCour()=="<=" ||
			ls.getSymCour()==">" || ls.getSymCour()==">=")
		ls.suivant();
	else
		erreur("<opRel>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::facteur() {
// <facteur> ::= <entier>  |  <variable>  |  <opUnaire> <expBool> | ( <expBool> )

	if (ls.getSymCour()=="<VARIABLE>" || ls.getSymCour()=="<ENTIER>")
		ls.suivant();
	else if (ls.getSymCour()=="-" || ls.getSymCour()=="non")
	{
		ls.suivant();
		expBool();
	}
	else if (ls.getSymCour()=="(")
	{
		ls.suivant();
		expBool();
		sauterSymCour(")");
	}
	else
		erreur("<facteur>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::opAdd()
// <opBinaire> ::= + | - | *  | /
{
	if (ls.getSymCour()=="+" || ls.getSymCour()=="-")
		ls.suivant();
	else
		erreur("<opAdd>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::opMult()
// <opBinaire> ::= + | - | *  | /
{
	if (ls.getSymCour()=="*" || ls.getSymCour()=="/")
		ls.suivant();
	else
		erreur("<opMult>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::testerSymCour(string ch) {
	if (ls.getSymCour() != ch) {
		cout << endl << "-------- Erreur ligne " << ls.getLigne()
				<< " - Colonne " << ls.getColonne() << endl << "   Attendu : "
				<< ch << endl << "   Trouve  : " << ls.getSymCour() << endl
				<< endl;
		cout<<ls.getSymCour()<<endl;
		exit(0); // plus tard, on levera une exception
	}
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::sauterSymCour(string ch) {
	testerSymCour(ch);
	ls.suivant();
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::erreur(string mess) {
	cout << endl << "-------- Erreur ligne " << ls.getLigne() << " - Colonne "
			<< ls.getColonne() << endl << "   Attendu : " << mess << endl
			<< "   Trouve  : " << ls.getSymCour() << endl << endl;
	exit(0); // plus tard, on levera une exception
}
